//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
#include <windows.h>
#include "ipl_cfg.h"
#include <bsp.h>
#include <bsp_cfg.h>
#include <boot.h>
#include "lcd_Defs.h"
#include "xllp_lcd.h"

//IPL runs in physical address.
// and the offset depends on the ipl.bib layout.
#define GUESS_FREE_SCRATCH_RAM (LITTLETON_BASE_PA_SDRAM + 0x03C00000)
#define GUESS_FREE_SCRATCH_RAM_LENGTH 320 * 240 * 2

//------------------------------------------------------------------------------
 
static
UINT16
*ps_tempImageBuffer;

//------------------------------------------------------------------------------

static
HANDLE
s_hStoreDevice = NULL;

static
LONG
s_storeRefCount = 0;

static
HANDLE
s_hDisplayDevice = NULL;

static
LONG
s_displayRefCount = 0;

static
HANDLE
s_hKeypadDevice = NULL;

static
LONG
s_keypadRefCount = 0;

//------------------------------------------------------------------------------

static
VOID
DisplayImage(
    UINT32 index
    )
{
    HANDLE hStore;
    HANDLE hDisplay;
    RECT rect;

    // Note, we temporarily store the image here before writing it to the screen
    // Need to find out if its worth it to allocate 240*320*2 bytes just to hold this
    // because it will max out the IPL's RAM, and if its worth it to reserve memory.
    // For now, use space we 'know' won't get touched between this line and 
    // the call to BootDisplayBltRect
    ps_tempImageBuffer = (UINT16 *) GUESS_FREE_SCRATCH_RAM;
    
    // Get boot store & display
    hStore = BootStoreGetHandle(0);
    hDisplay = BootDisplayGetHandle(BOOT_DISPLAY_PRIMARY);

    // Open reserved region
    if (!BootStoreOpenReservedRegion(hStore, BOOT_STORE_ACCESS_READ, "LOGO"))
        goto cleanUp;

    // Read image
    if (!BootStoreReadFromImageLib(
            hStore, index, &rect, ps_tempImageBuffer, GUESS_FREE_SCRATCH_RAM_LENGTH
            ))
        {
        BootStoreClose(hStore);
        goto cleanUp;
        }

    // Close store
    BootStoreClose(hStore);

    // Show it on display - use blt bitmap one because bitmap data 
    // is stored in reverse order
    BootDisplayBltRect(hDisplay, &rect, ps_tempImageBuffer);

cleanUp:
    BootDisplayReleaseHandle(hDisplay);
    BootStoreReleaseHandle(hStore);
    return;
}

//------------------------------------------------------------------------------

static
BOOL
ConfirmAction(
    UINT16 vkOk,
    UINT16 vkCancel
    )
{
    HANDLE hKeypad;
    BOOL rc, ok, cancel;

    hKeypad = BootKeypadGetHandle(0);
    if (hKeypad == NULL) goto cleanUp;

    // Wait until both ok & cancel keys are released
    do
        {
        ok = BootKeypadIsPressed(hKeypad, vkOk);
        cancel = BootKeypadIsPressed(hKeypad, vkCancel);
        }
    while (ok || cancel);

    // Now wait for first be pressed again    
    do
        {
        ok = BootKeypadIsPressed(hKeypad, vkOk);
        cancel = BootKeypadIsPressed(hKeypad, vkCancel);
        }
    while (!ok && !cancel);

    // Save result
    rc = ok;

    // Wait until both ok & cancel keys are released
    do
        {
        ok = BootKeypadIsPressed(hKeypad, vkOk);
        cancel = BootKeypadIsPressed(hKeypad, vkCancel);
        }
    while (ok || cancel);

cleanUp:
    BootKeypadReleaseHandle(hKeypad);    
    return rc;
}

//------------------------------------------------------------------------------

VOID
OEMBootNotify(
    UINT32 code,
    VOID* pData,
    UINT32 dataSize
    )
{
    static HANDLE hDisplay;
    BOOL *pConfirmed;
    
    switch (code)
        {
        case BOOT_NOTIFY_POWERON:
            // Get display handle which will hold display opened
            // until we will close it in BOOT_NOTIFY_RUN...
            hDisplay = BootDisplayGetHandle(0);
            DisplayImage(0);
            break;
        case BOOT_NOTIFY_RUN:
            // Following commands will switch off backlight and
            // display. However we want to see logo until main OS
            // display driver get intialized...
            // BootDisplayReleaseHandle(hDisplay);       
            break;
        case BOOT_NOTIFY_ERASE:
            pConfirmed = (BOOL*)pData;
            DisplayImage(1);
            *pConfirmed = ConfirmAction(VK_TSOFT1, VK_TSOFT2);
            DisplayImage(0);
            break;
        case BOOT_NOTIFY_ULDR:
            pConfirmed = (BOOL*)pData;
            DisplayImage(2);
            *pConfirmed = ConfirmAction(VK_TSOFT1, VK_TSOFT2);
            DisplayImage(0);
            break;            
        case BOOT_NOTIFY_CHARGING:
            OALMSG(OAL_ERROR, (L"ERROR: OEMBootNotify: "
                L"Charging through IPL framework unsupported\r\n"
                ));
            break;
        }
}
    
//------------------------------------------------------------------------------

HANDLE
OEMBootGetDeviceHandle(
    UINT32 deviceClass,
    UINT32 deviceIndex
    )
{
    HANDLE hDevice = NULL;

    switch (deviceClass)
        {
        case BOOT_DEVICE_CLASS_STORE:
            if (s_hStoreDevice == NULL) 
                {
                s_hStoreDevice = BootStoreInit(&g_bootStoreInit);
                }
            hDevice = s_hStoreDevice;
            if (hDevice != NULL) s_storeRefCount++;
            break;
        case BOOT_DEVICE_CLASS_DISPLAY:
            if (s_hDisplayDevice == NULL)
                {
                BOOT_DEVICE_INIT init;
                BOOT_DISPLAY_LITTLETON_INIT_CONTEXT context;

                context.type = (BOOT_DISPLAY_TYPE)deviceIndex;
                init.pfnInit = BootDisplayLittletonInit;
                init.pContext = &context;
                init.contextSize = sizeof(context);
                s_hDisplayDevice = BootDisplayInit(&init);
                }
            hDevice = s_hDisplayDevice;
            if (hDevice != NULL) s_displayRefCount++;
            break;
        case BOOT_DEVICE_CLASS_KEYPAD:
            if (s_hKeypadDevice == NULL)
                {
                BOOT_DEVICE_INIT init;

                init.pfnInit = BootKeypadLittletonInit;
                init.pContext = NULL;
                init.contextSize = 0;
                s_hKeypadDevice = BootKeypadInit(&init);
                }
            hDevice = s_hKeypadDevice;
            if (hDevice != NULL) s_keypadRefCount++;
            break;
        case BOOT_DEVICE_CLASS_BATTERY:
        case BOOT_DEVICE_CLASS_LED:
            OALMSG(OAL_ERROR, (L"ERROR: OEMBootGetDeviceHandle: "
                L"Unsupported BOOT_DEVICE requested\r\n"
                ));
            break;
        }
    
    return hDevice;
}

//------------------------------------------------------------------------------

VOID
OEMBootReleaseDeviceHandle(
    HANDLE hDevice
    )
{
    if (hDevice == s_hStoreDevice)
        {
        if (--s_storeRefCount == 0) 
            {
            // Prevents image from loading?
            // BootStoreDeinit(hDevice);
            s_hStoreDevice = NULL;
            }
        }
    else if (hDevice == s_hDisplayDevice)
        {
        if (--s_displayRefCount == 0) 
            {
            BootDisplayDeinit(hDevice);
            s_hDisplayDevice = NULL;
            }
        }
    else if (hDevice == s_hKeypadDevice)
        {
        if (--s_keypadRefCount == 0) 
            {
            BootKeypadDeinit(hDevice);
            s_hKeypadDevice = NULL;
            }
        }
  }

//------------------------------------------------------------------------------


